package com.rookie.tool.module.util.sql;

import org.springframework.util.StringUtils;

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author rookie
 */
public class SqlToBeanUtils {

    private static final Pattern LINE_PATTERN = Pattern.compile("_(\\w)");

    /**
     * 将字符型的sql转实体类
     */
    private static MySqlTable sqlResolve(String sql) {
        MySqlTable mySqlTable = new MySqlTable();
        if (!StringUtils.hasText(sql)) {
            return null;
        }
        String dealText = "";
        int tableIndex = sql.toLowerCase().indexOf("create table");

        if (tableIndex == -1) {
            return null;
        }
        int startSplit = sql.indexOf("`") + 1;
        int endSplit = sql.indexOf("`", startSplit);

        if (substringVerify(startSplit, endSplit)) {
            String tableName = sql.substring(startSplit, endSplit);
            if (!StringUtils.hasText(tableName)) {
                throw new RuntimeException("类名为空");
            }
            mySqlTable.setTableName(tableName);
        } else {
            return null;
        }

        dealText = sql.substring(endSplit);

        startSplit = dealText.indexOf("(") + 1;
        endSplit = dealText.lastIndexOf(")");

        String fields = "";
        if (substringVerify(startSplit, endSplit)) {
            fields = dealText.substring(startSplit, endSplit);
        } else {
            return null;
        }

        String[] split = fields.split(",");
        List<MySqlTable.SqlField> fieldList = new LinkedList<>();
        for (String s : split) {
            MySqlTable.SqlField tmp = initField(s);
            if (tmp != null) {
                fieldList.add(tmp);
            }
        }
        mySqlTable.setFields(fieldList);

        dealText = dealText.substring(endSplit + 1);

        startSplit = dealText.indexOf("'") + 1;
        endSplit = dealText.indexOf("'", startSplit);

        if (substringVerify(startSplit, endSplit)) {
            mySqlTable.setComment(dealText.substring(startSplit, endSplit));
        }
        return mySqlTable;
    }

    /**
     * 获取字段信息
     *
     * @param text 截取的字段sql
     * @return 字段信息
     */
    private static MySqlTable.SqlField initField(String text) {
        MySqlTable.SqlField sqlField = new MySqlTable.SqlField();
        int startSplit = text.indexOf("`") + 1;
        int endSplit = text.indexOf("`", startSplit);

        if (substringVerify(startSplit, endSplit)) {
            sqlField.setFieldName(text.substring(startSplit, endSplit));
        } else {
            return null;
        }

        String dealText = text.substring(endSplit + 1);
        dealText = dealText.trim();
        endSplit = dealText.indexOf(" ");
        if (substringVerify(startSplit, endSplit)) {
            String substring = dealText.substring(0, endSplit);
            substring = substring.replaceAll("\\(\\s*\\d*\\s*\\)", "");
            substring = substring.replaceAll("\\(\\s*\\d*\\s*，\\s*\\d*\\s*\\)", "");
            String typeOfJava = MysqlEnum.getTypeOfJava(substring);

            if (!StringUtils.hasText(typeOfJava)) {
                typeOfJava = "Object";
            }
            sqlField.setFieldType(typeOfJava);
        } else {
            return null;
        }

//        反转截取
        dealText = new StringBuilder(dealText).reverse().toString();
        startSplit = dealText.indexOf("'") + 1;
        endSplit = dealText.indexOf("'", startSplit);

        if (substringVerify(startSplit, endSplit)) {
            String tmp = dealText.substring(startSplit, endSplit);
            sqlField.setComment(new StringBuilder(tmp).reverse().toString());
        }
        return sqlField;
    }

    /**
     * 截取验证
     *
     * @param start 开始位置
     * @param end   结束位置
     * @return 验证结果
     */
    private static boolean substringVerify(int start, int end) {
        return start != 0 && end != -1 && start <= end;
    }

    /**
     * 首字母大写
     *
     * @param str 字符串
     * @return 结果
     */
    public static String upperCase(String str) {
        if ((str == null) || (str.length() == 0)) {
            return str;
        }
        char[] ch = str.toCharArray();
        if (ch[0] >= 'a' && ch[0] <= 'z') {
            ch[0] = (char) (ch[0] - 32);
        }
        return new String(ch);
    }


    /**
     * 拼接sql语句
     *
     * @return 结果
     */
    public static String appendSqlString(MySqlTable mySqlTable, TableConfig tableConfig) {
        if (mySqlTable == null) {
            throw new RuntimeException("解析失败");
        }
        StringBuilder beanString = new StringBuilder();
        String startString = "/**\n * " + mySqlTable.getComment() + "\n **/\n";
        startString += "public class %s {\n";
        String tableName = mySqlTable.getTableName();

        if (tableName.contains("_")) {
            tableName = lineToHump(tableName);
        }
//        首字母大写
        tableName = upperCase(tableName);
        beanString.append(String.format(startString, tableName));
        List<MySqlTable.SqlField> fields = mySqlTable.getFields();

        for (MySqlTable.SqlField field : fields) {
            if (StringUtils.hasText(field.getComment())) {
                beanString.append("\t\t/**\n \t\t* ")
                        .append(field.getComment())
                        .append("\n \t\t**/\n");
            }

            String fileName = field.getFieldName();

            if (tableConfig != null && tableConfig.getIsFieldHump() != null && tableConfig.getIsFieldHump() == 1 && fileName.contains("_")) {
                fileName = lineToHump(fileName);
            }
            beanString.append(String.format("\t private %s %s;", field.getFieldType(), fileName)).append("\n");
        }
        beanString.append("}");
        return beanString.toString();
    }

    /**
     * 下划线转驼峰
     *
     * @param str 字符串
     * @return 结果
     */
    public static String lineToHump(String str) {
        str = str.toLowerCase();
        Matcher matcher = LINE_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }


    /**
     * 特殊字符替换
     *
     * @return 结果
     */
    private static String specialWordReplace(String str) {
        String reg = "COMMENT\\s*'(.)+?\\s*'\\s*,";
        Matcher matcher = Pattern.compile(reg,Pattern.CASE_INSENSITIVE).matcher(str);
        while (matcher.find()){
            String group = matcher.group();
            String newWord = group.substring(0,group.length() - 1).replaceAll(",","，");
            str = str.replace(group,newWord + ",");
        }

        reg = "decimal\\(\\s*[0-9]+\\s*,\\s*[0-9]+\\s*\\)";
        matcher = Pattern.compile(reg,Pattern.CASE_INSENSITIVE).matcher(str);
        while (matcher.find()){
            String group = matcher.group();
            String newWord = group.replaceAll(",","，");
            str = str.replace(group,newWord);
        }
        return str;
    }

    /**
     * 输入创建表的sql语句
     *
     * @param args 参数
     */
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder line = new StringBuilder();
        System.out.println("请输入SQL字符串：\n");
        while (true) {
            String text = scanner.nextLine();
            if ("exit".equals(text)) {
                break;
            }
            line.append(text);
        }
        String str = specialWordReplace(line.toString());
        MySqlTable mySqlTable = sqlResolve(str);
        System.out.println(appendSqlString(mySqlTable, new TableConfig().setIsFieldHump(1)));

    }
}
